package com.jdyfy.controller;

import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jdyfy.dto.HistoTaskDTO;
import com.jdyfy.dto.ProjectDTO;
import com.jdyfy.dto.StatisticsDTO;
import com.jdyfy.entity.Notification;
import com.jdyfy.entity.Project;
import com.jdyfy.entity.User;
import com.jdyfy.entity.WinNotiProject;
import com.jdyfy.mapper.ProjectMapper;
import com.jdyfy.mapper.WinNotiProjectMapper;
import com.jdyfy.result.Result;
import com.jdyfy.service.NotificationService;
import com.jdyfy.service.ProjectService;
import com.jdyfy.service.WinNotiProjectService;
import com.jdyfy.utils.TokenUtils;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 项目控制层
 *
 */

@RestController
@RequestMapping("/jdyfy")
@Slf4j
public class ProjectController {

    @Autowired
    private ProjectService projectService;

    @Autowired
    private ProjectMapper projectMapper;

    @Autowired
    private WinNotiProjectService winNotiProjectService;


    @Autowired
    private WinNotiProjectMapper winNotiProjectMapper;

    @Autowired
    private NotificationService notificationService;

    /**
     * 获取项目总数
     * @return
     */
    @GetMapping("/projectTotal")
    public Result<Long> projectTotal() {
        long totalUsers = projectService.count(); // 调用 count 方法
        return Result.success(totalUsers);
    }

    /**
     * 查询所有项目
     * @return
     */
    @GetMapping("/projects")
    public Result<List<Project>> getAllProject() {
        List<Project> project = projectService.list();
        return Result.success(project);
    }

    /**
     * 根据状态查询项目
     * @param
     * @return
     */
    @GetMapping("/getProjectsByStatus")
    public Result<List<Project>> getProjectsByStatus(@RequestParam Integer annoStatusStart,@RequestParam Integer annoStatusEnd) {
        List<Project> project = projectService.getProjectsByStatus(annoStatusStart,annoStatusEnd);
        return Result.success(project);
    }

    /**
     * 根据状态查询项目
     * @param
     * @return
     */
    @GetMapping("/getProjectsBySStatus")
    public Result<List<Project>> getProjectsBySStatus(@RequestParam Integer status) {
        QueryWrapper<Project> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", status);
        List<Project> project = projectMapper.selectList(queryWrapper);
        return Result.success(project);
    }

    /**
     * 根据id查询项目
     * @param projectId
     * @return
     */
    @GetMapping("/project/{projectId}")
    public Result<Project> getProjectById(@PathVariable Long projectId) {
        Project project = projectMapper.selectById(projectId);
        return Result.success(project);
    }

    /**
     * 根据项目编号查询项目
     * @param projectNumber
     * @return
     */
    @GetMapping("/projectByNumber/{projectNumber}")
    public Result<Project> getProjectByNumber(@PathVariable String projectNumber) {
        Project project = projectService.selectByNumber(projectNumber);
        return Result.success(project);
    }

    /**
     * 新增,修改项目
     * @param project
     * @return
     */
    @PostMapping("/project/save")
    public boolean addOrUpdateProject(@RequestBody Project project) {
        return projectService.saveOrUpdate(project);
    }

    /**
     * 根据id批量删除
     * @param ids
     * @return
     */
    @DeleteMapping("/project/dels")
    public int deleteByIds(@RequestBody List<Long> ids) {
        return projectService.delByIds(ids);
    }

    /**
     * 分页获取项目数据（mybatis-plus）
     *  pageNum=((pageNum-1) * pageSize)
     */
    @GetMapping("/projectPage")
    public Result<IPage<Project>> getProjectPage(@RequestParam Integer pageNum,
                                                 @RequestParam Integer pageSize,
                                                 @RequestParam String projectNumber,
                                                 @RequestParam String projectName,
                                                 @RequestParam String procurementMethod) {
        //创建分页对象
        IPage<Project> page = new Page<>(pageNum, pageSize);
        //创建查询对象
        QueryWrapper<Project> queryWrapper = new QueryWrapper<>();

        //添加条件查询
        if (projectNumber != null && !projectNumber.isEmpty()) {
            queryWrapper.like("project_number", projectNumber);
        }
        if (projectName != null && !projectName.isEmpty()) {
            queryWrapper.like("project_name", projectName);
        }
        if (procurementMethod != null && !procurementMethod.isEmpty()) {
            queryWrapper.like("procurement_method", procurementMethod);
        }

        //按序号倒叙排序
        queryWrapper.orderByDesc("project_id");

        //获取当前用户信息
        User currentUser = TokenUtils.getCurrentUser();
        System.out.println("6666666666666666" + currentUser.getUsername());

        //执行查询
        IPage<Project> IPage = projectService.page(page, queryWrapper);
        return Result.success(IPage);
    }

    /**
     * 分页获取根据状态排过序的项目数据（mybatis-plus）
     */
    @GetMapping("/projectPageSortByStatus")
    public Result<IPage<Project>> getProjectPageSortByStatus(@RequestParam Integer pageNum,
                                                 @RequestParam Integer pageSize,
                                                 @RequestParam String projectNumber,
                                                 @RequestParam String projectName,
                                                 @RequestParam String procurementMethod) {
        //创建分页对象
        IPage<Project> page = new Page<>(pageNum, pageSize);
        //创建查询对象
        QueryWrapper<Project> queryWrapper = new QueryWrapper<>();

        //添加条件查询
        if (projectNumber != null && !projectNumber.isEmpty()) {
            queryWrapper.like("project_number", projectNumber);
        }
        if (projectName != null && !projectName.isEmpty()) {
            queryWrapper.like("project_name", projectName);
        }
        if (procurementMethod != null && !procurementMethod.isEmpty()) {
            queryWrapper.like("procurement_method", procurementMethod);
        }

        // 添加排除 status = 0 的条件
        //queryWrapper.ne("status", 0);

        //按序号倒叙排序
        queryWrapper.orderByAsc("status");

        //执行查询
        IPage<Project> IPage = projectService.page(page, queryWrapper);
        return Result.success(IPage);
    }

    /**
     * 分页获取根据状态范围查询项目数据（mybatis-plus）
     */
    @GetMapping("/projectPageByStatus")
    public Result<IPage<Project>> getProjectPageByStatus(@RequestParam Integer pageNum,
                                                             @RequestParam Integer pageSize,
                                                             @RequestParam String projectNumber,
                                                             @RequestParam String projectName,
                                                             @RequestParam String procurementMethod,
                                                            @RequestParam Integer statusStart,
                                                            @RequestParam Integer statusEnd) {
        //创建分页对象
        IPage<Project> page = new Page<>(pageNum, pageSize);
        //创建查询对象
        QueryWrapper<Project> queryWrapper = new QueryWrapper<>();

        //添加条件查询
        if (projectNumber != null && !projectNumber.isEmpty()) {
            queryWrapper.like("project_number", projectNumber);
        }
        if (projectName != null && !projectName.isEmpty()) {
            queryWrapper.like("project_name", projectName);
        }
        if (procurementMethod != null && procurementMethod.isEmpty()) {
            queryWrapper.like("procurement_method", procurementMethod);
        }

        // 添加status范围查询
        if (statusStart != null && statusEnd != null) {
            queryWrapper.between("status", statusStart, statusEnd);
        }

        //执行查询
        IPage<Project> IPage = projectService.page(page, queryWrapper);
        return Result.success(IPage);
    }

    /**
     * 分页获取根据公告状态的范围查询项目数据（mybatis-plus）
     * @return
     */
    @GetMapping("/projectPageByStatusSpace")
    public Result<IPage<Project>> getProjectPageByStatusSpace(@RequestParam Integer pageNum,
                                                         @RequestParam Integer pageSize,
                                                         @RequestParam String projectNumber,
                                                         @RequestParam String projectName,
                                                         @RequestParam String procurementMethod,
                                                         @RequestParam Integer annoStatusStart,
                                                         @RequestParam Integer annoStatusEnd) {
        //创建分页对象
        IPage<Project> page = new Page<>(pageNum, pageSize);
        //创建查询对象
        QueryWrapper<Project> queryWrapper = new QueryWrapper<>();

        //添加条件查询
        if (projectNumber != null && !projectNumber.isEmpty()) {
            queryWrapper.like("project_number", projectNumber);
        }
        if (projectName != null && !projectName.isEmpty()) {
            queryWrapper.like("project_name", projectName);
        }
        if (procurementMethod != null && !procurementMethod.isEmpty()) {
            queryWrapper.like("procurement_method", procurementMethod);
        }
        // 添加annoStatus范围查询
        if (annoStatusStart != null && annoStatusEnd != null) {
            queryWrapper.between("anno_status", annoStatusStart, annoStatusEnd);
        }

        //按序号倒叙排序
        queryWrapper.orderByAsc("status");

        //执行查询
        IPage<Project> IPage = projectService.page(page, queryWrapper);
        return Result.success(IPage);
    }



    /**
     * 导出项目数据
     */
    @GetMapping("/project/export")
    public void export(HttpServletResponse response) throws IOException {
        // 从数据库查询所有数据
        List<Project> list = projectService.list();

        // 状态映射表
        Map<Integer, String> statusMap = new HashMap<>();
        statusMap.put(0, "待进行");
        statusMap.put(1, "待公告");
        statusMap.put(2, "已公告");
        statusMap.put(3, "待公示");
        statusMap.put(4, "已公示");
        statusMap.put(5, "已完成");
        statusMap.put(6, "已归档");

        // 创建一个新的列表，用于存放转换后的数据
        List<ProjectDTO> dtoList = new ArrayList<>();

        for (Project project : list) {
            // 创建 ProjectDTO 对象，并将所需字段复制到 DTO
            ProjectDTO dto = new ProjectDTO();
            dto.setProjectId(project.getProjectId());
            dto.setProjectNumber(project.getProjectNumber());
            dto.setProjectName(project.getProjectName());
            dto.setProjectType(project.getProjectType());
            dto.setQuantity(project.getQuantity());
            dto.setBudget(project.getBudget());
            dto.setPublishDate(project.getPublishDate());
            // 使用状态映射表将数字转换为中文状态
            dto.setStatus(statusMap.get(project.getStatus()));
            dto.setProcurementType(project.getProcurementType());
            dto.setProcurementMethod(project.getProcurementMethod());
            dto.setFundingSource(project.getFundingSource());
            dto.setTenderOfficer(project.getTenderOfficer());
            dto.setApplyingDepartment(project.getApplyingDepartment());
            dto.setApplicant(project.getApplicant());
            dto.setMeetingRoom(project.getMeetingRoom());
            dto.setProcurementText(project.getProcurementText());
            dto.setDealer(project.getDealer());
            dto.setConsultationFileUrl(project.getConsultationFileUrl());
            dto.setArchiveTime(project.getArchiveTime());

            // 将转换后的 DTO 添加到列表
            dtoList.add(dto);
        }
        // 创建一个 ExcelWriter
        ExcelWriter writer = ExcelUtil.getWriter(true);

        // 自定义标题别名
        writer.addHeaderAlias("projectId", "项目id");
        writer.addHeaderAlias("projectNumber", "项目编号");
        writer.addHeaderAlias("projectName", "项目名称");
        writer.addHeaderAlias("projectType", "项目类型");
        writer.addHeaderAlias("quantity", "数量");
        writer.addHeaderAlias("budget", "预算（万元）");
        writer.addHeaderAlias("publishDate", "发布时间");
        writer.addHeaderAlias("status", "状态");
        writer.addHeaderAlias("procurementType", "采购类型");
        writer.addHeaderAlias("procurementMethod", "采购方式");
        writer.addHeaderAlias("fundingSource", "资金来源");
        writer.addHeaderAlias("tenderOfficer", "招标人");
        writer.addHeaderAlias("applyingDepartment", "申请部门");
        writer.addHeaderAlias("applicant", "申请人");
        writer.addHeaderAlias("meetingRoom", "会议室");
        writer.addHeaderAlias("procurementText", "采购内容");
        writer.addHeaderAlias("dealer", "成交人（品牌）");
        writer.addHeaderAlias("consultationFileUrl", "磋商文件地址");
        writer.addHeaderAlias("archiveTime", "归档时间");

        // 将数据写入到 Excel
        writer.write(dtoList, true);

        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        // 设置文件名
        String fileName = URLEncoder.encode("项目数据", "UTF-8");
        // 设置文件类型
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");

        // 输出
        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        out.close();
        writer.close();
    }

    /**
     * 科室数据统计
     * @return
     */
    @GetMapping("/SPBar")
    public Result<Map<String,Object>> getSPBarCharts() {
        // 根据科室分类获取项目的数据和数量，分别存入两个数组
        StatisticsDTO barCharts = projectService.getSPBarCharts();
        Map<String,Object> map = new HashMap<>();
        map.put("y",barCharts.getAppArray());
        map.put("x",barCharts.getCountArray());
        return Result.success(map);
    }

    /**
     * 项目类型统计
     * @return
     */
    @GetMapping("/PT")
    public Result<Map<String, Integer>> getPTCharts() {
        // 根据项目类型分类获取项目的数据和数量，
        Map<String, Integer> Charts = projectService.getPTCharts();
        return Result.success(Charts);
    }

    /**
     * 项目采购方式统计
     * @return
     */
    @GetMapping("/PM")
    public Result<Map<String, Integer>> getPMCharts() {
        // 根据项目类型分类获取项目的数据和数量，
        Map<String, Integer> Charts = projectService.getPMCharts();
        return Result.success(Charts);
    }

    /**
     * 更新或新增中标项目
     * @param winNotiProject
     * @return
     */
    @PostMapping("/winnotiProject/save")
    public boolean addOrUpdateWinProject(@RequestBody WinNotiProject winNotiProject) {
        boolean b = winNotiProjectService.saveOrUpdate(winNotiProject);
        if(b){
            Notification notification = Notification.builder()
                    .message(String.format("恭喜您，您参加的项目编号为{%s}项目已中标，请留意后续消息。", winNotiProject.getProjectNumber()))
                    .type("中标提醒")
                    .timestamp(LocalDateTime.now())
                    .departmentName(winNotiProject.getDealer())
                    .isRead(0)  // 未读
                    .handleStatus(0)  // 未处理
                    .build();
            notificationService.saveOrUpdate(notification);
        }
        return b;
    }

    //中标项目分页查询
    @GetMapping("/winnotiProjectByDealerPage")
    public Result<Map<String, Object>> getWinnotiProjectByDealerPage(@RequestParam Integer pageNum,
                                                               @RequestParam Integer pageSize,
                                                               @RequestParam String projectName,
                                                               @RequestParam String projectNumber,
                                                               @RequestParam String departmentName) {
        List<Project> list = winNotiProjectService.getWinnotiProjectByDealer(departmentName);

        // 如果 projectName 和 projectNumber 不为空，则进行过滤
        if (projectName != null && !projectName.isEmpty()) {
            list = list.stream()
                    .filter(project -> project.getProjectName().contains(projectName))  // 根据项目名称进行模糊匹配
                    .collect(Collectors.toList());
        }

        if (projectNumber != null && !projectNumber.isEmpty()) {
            list = list.stream()
                    .filter(project -> project.getProjectNumber().contains(projectNumber))  // 根据项目编号进行模糊匹配
                    .collect(Collectors.toList());
        }

        // 获取总记录数
        int totalCount = list.size();

        // 计算分页后的数据
        List<Project> paginatedList = getPaginatedProjects(list, pageNum, pageSize);

        // 计算总页数
        int totalPages = (int) Math.ceil((double) totalCount / pageSize);

        // 将分页信息和分页数据封装在一个 Map 中
        Map<String, Object> result = new HashMap<>();
        result.put("records", paginatedList);
        result.put("pages", totalPages);
        result.put("current", pageNum);
        result.put("size", pageSize);
        result.put("total", totalCount);  // 返回符合条件的总记录数

        return Result.success(result);
    }

    // 分页查询方法
    public List<Project> getPaginatedProjects(List<Project> list, int pageNumber, int pageSize) {
        int fromIndex = (pageNumber - 1) * pageSize;
        if (fromIndex >= list.size()) {
            return List.of(); // 超出范围时返回空列表
        }
        int toIndex = Math.min(fromIndex + pageSize, list.size());
        return list.subList(fromIndex, toIndex);
    }

    //根据项目编号查询中标项目
    @GetMapping("/winnotiByProjectNumber/{projectNumber}")
    public Result<WinNotiProject> getWinProjectByNumber(@PathVariable String projectNumber) {
        WinNotiProject winNotiProject = winNotiProjectService.getOne(new QueryWrapper<WinNotiProject>().eq("project_number", projectNumber));
        return Result.success(winNotiProject);
    }

    // 获取中标项目总数
    @GetMapping("/winnotiProjectCount")
    public Result<Long> getWinProjectCount() {
        Long count = winNotiProjectService.count();
        return Result.success(count);
    }

    // 获取中标总金额
    @GetMapping("/totalAmount")
    public Result<BigDecimal> getTotalAmount() {
        QueryWrapper<WinNotiProject> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("SUM(final_money)");  // 使用SQL聚合函数

        List<Object> result = winNotiProjectMapper.selectObjs(queryWrapper);
        BigDecimal sum = (BigDecimal) result.get(0);
        return Result.success(sum);
    }

    //历史任务查询
    @GetMapping("/histoProjectPage")
    public Result<Map<String, Object>> getHistoProjectByDealerPage(@RequestParam Integer pageNum,
                                                                     @RequestParam Integer pageSize,
                                                                     @RequestParam String projectName,
                                                                     @RequestParam String projectNumber,
                                                                     @RequestParam String procurementMethod) {
        //先根据特定条件查询出数据
        List<HistoTaskDTO> list = projectService.getHistoProject(6);

        // 如果 projectName 和 projectNumber 不为空，则进行过滤（搜索的功能）
        if (projectName != null && !projectName.isEmpty()) {
            list = list.stream()
                    .filter(project -> project.getProjectName().contains(projectName))  // 根据项目名称进行模糊匹配
                    .collect(Collectors.toList());
        }

        if (projectNumber != null && !projectNumber.isEmpty()) {
            list = list.stream()
                    .filter(project -> project.getProjectNumber().contains(projectNumber))  // 根据项目编号进行模糊匹配
                    .collect(Collectors.toList());
        }

        if (procurementMethod != null && !procurementMethod.isEmpty()) {
            list = list.stream()
                    .filter(project -> project.getProcurementMethod().contains(procurementMethod))  // 根据项目采购类型进行模糊匹配
                    .collect(Collectors.toList());
        }

        // 获取总记录数
        int total = list.size();

        // 计算分页后的数据
        List<HistoTaskDTO> records = getPaginatedProjectss(list, pageNum, pageSize);

        // 计算总页数
        int pages = (int) Math.ceil((double) total / pageSize);

        // 将分页信息和分页数据封装在一个 Map 中
        Map<String, Object> result = new HashMap<>();
        result.put("records", records);
        result.put("pages", pages);
        result.put("current", pageNum);
        result.put("size", pageSize);
        result.put("total", total);  // 返回符合条件的总记录数

        return Result.success(result);
    }

    // 分页查询方法
    public List<HistoTaskDTO> getPaginatedProjectss(List<HistoTaskDTO> list, int pageNumber, int pageSize) {
        int fromIndex = (pageNumber - 1) * pageSize;
        if (fromIndex >= list.size()) {
            return List.of(); // 超出范围时返回空列表
        }
        int toIndex = Math.min(fromIndex + pageSize, list.size());
        return list.subList(fromIndex, toIndex);
    }

    // 根据部门名称获取总金额
    @GetMapping("/totalAmountByDepartmentName")
    public Result<BigDecimal> getTotalAmountByDepartmentName(@RequestParam String departmentName) {
        QueryWrapper<WinNotiProject> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dealer", departmentName);
        queryWrapper.select("SUM(final_money)");  // 使用SQL聚合函数

        List<Object> result = winNotiProjectMapper.selectObjs(queryWrapper);
        BigDecimal sum = (BigDecimal) result.get(0);
        return Result.success(sum);
    }
}
